; void umbralizar(char* matriz, unsigned alto, unsigned ancho, unsigned altoAncho, char umbralSup, char umbralInf)
global umbralizar
section .text
%define matriz_p [ebp + 8]
%define alto [ebp + 12]
%define ancho [ebp + 16]
%define altoAncho [ebp + 20]
%define uSup [ebp + 24]
%define uInf [ebp + 28]
umbralizar:
push ebp
mov ebp, esp
push ebx
push edi
push esi
xor eax, eax
xor edx, edx
mov al, uSup
mov dl, al
mov dh, al
mov ah, dl
shl eax, 16
add ax, dx
xor edx, edx
mov dl, al
;eax= [uSup | uSup | uSup | uSup]
movd mm0, eax
movd mm1, eax
psllq mm1, 32
paddb mm0, mm1 ; mm0 <- uSup en cada byte
movq mm1, mm0 ; mm1 tiene una copia de mm0 para poder pisarlo
mov ecx, altoAncho ; ecx tiene  la cantidad total de elementos, la uso en el primer ciclo de umbralizar
mov edi, matriz_p ; puntero a la matriz
mov esi, edi ; copia del puntero para no volver a leerlo de memoria
pxor mm7,mm7 ; mm7 <- 0

ciclo:
cmp ecx, 8
jb ultimos ; si me quedan menos de 8 los proceso a mano
movq mm2, [esi] ;cargo los datos
psubusb mm1, mm2 ; hago umbral - dato. donde me queda 0 es porq el dato era mayor q el umbral
pcmpeqb mm1, mm7 ; comparando con 0 me armo la mascara
por mm2, mm1 ;al hacer or me queda 255 en los mas altos y los otros sin variar
movq [esi], mm2 ; lo guardo
add esi, 8 ; proximos datos
movq mm1, mm0 ; recupero el umbral
sub ecx, 7 ; procese 8 elementos, resto 7 y uno del loop
loop ciclo
jmp continuar
ultimos: ;llego aca cuando tengo menos de 8 elementos
cmp ecx, 0
je continuar

cicloUltimos:
;los ultimos 8 se procesan con registros de proposito general
mov al, [esi]
cmp al, dl
ja cambiar
inc esi
loop cicloUltimos
jmp continuar
cambiar: ;si era saturo
mov byte [esi], 255
inc esi
loop cicloUltimos


;hasta ahora tengo en 255 los mayores al umbral superior.
 continuar:
xor eax, eax ; eax <-0
xor edx, edx ; edx <- 0
mov al, uInf ;al <- uInf
mov dl, al
mov dh, al
mov ah, dl
shl eax, 16
add ax, dx
xor edx, edx
mov dl, al
;eax= [uInf | uInf | uInf | uInf]
movd mm0, eax
movd mm1, eax
psllq mm1, 32
paddb mm0, mm1 ; mm0 <- uInf en cada byte
movq mm1, mm0 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; mm1, mm0 uInf
; mm2 255
; ecx, contador alto
; ebx, contador ancho
; ebp copia del ancho
; mm7 0
; esi puntero
; eax manejo manual de datos
; edx flag de encontre alguno
; edi aux para el flag
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov eax, 0xFFFFFFFF
movd mm2, eax
movd mm3, eax
psllq mm2, 32
paddb mm2, mm3 ; mm2 <- FFFF............FF

mov ecx, alto ;ecx <- alto
cmp ecx, 2
jbe finCicloHisteresis
mov esi, matriz_p ; esi <-matriz_p
mov ebp, ancho ; ebp <- ancho
add esi, ebp ; salto la primer fila
sub ecx, 2 ; ecx tiene el numero exacto de filas a procesar
xor edi, edi ; edi <-0
xor eax, eax ; eax <- 0
mov al, dl ; al <- uInf
xor edx, edx
pxor mm7, mm7
cmp ebp, 2
jbe finCicloHisteresis
cicloHisteresis:
cmp ecx, 0
je finCicloHisteresisAux
mov ebx, ebp ;recargo el ancho
sub ebx, 2 ; resto 2 para tener la cantidad exacta a procesar
mov [esi], byte 0
add esi,1  ; salto el elemento de la primer columna
cicloHisteresis2:
pxor mm6, mm6 ; mm6 <- 0
cmp ebx, 8 ; si me quedan menos que 8 los hago a mano
jb procesarUltimosAux 
movq mm1, mm0 ;mm1 <- uInf en cada byte
movq mm3, [esi]; mm3 <- datos
psubusb mm1, mm3 ; umbral - dato
pcmpeqb mm1, mm7 ; donde me quedo 0 es porq dato >= umbral
;proceso vecinos
; en mm6 voy guardando un or de vecinos == 255
dec esi
;atras
movq mm4, [esi]
pcmpeqb mm4, mm2
por mm6, mm4
;atras abajo
movq mm4, [esi+ebp]
pcmpeqb mm4, mm2
por mm6, mm4
sub esi, ebp
; atras arriba
movq mm4, [esi]
pcmpeqb mm4, mm2
por mm6, mm4
inc esi
;arriba
movq mm4, [esi]
pcmpeqb mm4, mm2
por mm6, mm4
add esi, ebp
jmp adelante
 finCicloHisteresisAux:
 jmp finCicloHisteresis
procesarUltimosAux:
jmp procesarUltimos
adelante:
;adelante
movq mm4, [esi+1]
pcmpeqb mm4, mm2
por mm6, mm4
;adelante arriba
movq mm4, [esi+ebp+1]
pcmpeqb mm4, mm2
por mm6, mm4
sub esi, ebp
;adelante abajo
movq mm4, [esi+1]
pcmpeqb mm4, mm2
por mm6, mm4
add esi, ebp
;abajo
movq mm4, [esi+ebp]
pcmpeqb mm4, mm2
por mm6, mm4


pand mm1, mm6 ; condicion de borde: mayor q el umbralInf y algun vecino borde

por mm3, mm1 ;hago or con los datos
pcmpeqb mm3, mm2
movq [esi], mm3
sub ebx, 8
add esi, 8
jmp cicloHisteresis2

procesarUltimos:
ciclo2h:  cmp ebx, 0 ;procesamos de a uno los ultimos 8
          je finCicloHisteresis2 
          cmp byte [esi], 255
          je proximo
          cmp [esi], al
          jae puedeSer
          jmp noEra
          jmp ciclo2h
          ; simil a la implementacion del tp anterior   
puedeSer: cmp byte [esi + 1], 255
          je era   
          cmp byte [esi - 1], 255
          je era 
          cmp byte [esi + ebp], 255
          je era 
          cmp byte [esi + ebp + 1], 255
          je era  
          cmp byte [esi + ebp - 1], 255
          je era
          sub esi, ebp
          cmp byte [esi +1], 255
          je sumaYera
          cmp byte [esi -1], 255
          je sumaYera
          cmp byte [esi], 255
          je sumaYera
          add esi, ebp
          jmp noEra
sumaYera:  add esi, ebp ;restablezco el puntero
era:      mov byte [esi], 255 ; si era lo saturo
          inc esi ;acomodo puntero y contador
          dec ebx
          jmp ciclo2h
noEra:    mov byte [esi], 0 ;si no era, pongo un 0 (x q solo hacemos una pasada)
proximo:  
          
          inc esi
          dec ebx
          jmp ciclo2h  
finCicloHisteresis2: 
;termine una fila, me paro en la segunda columna de la otra fila
sub ecx, 1
mov [esi], byte 0
add esi, 1
jmp cicloHisteresis

finCicloHisteresis:
;desarmo el stack frame
pop esi
pop edi
pop ebx
pop ebp
ret               